home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk3 / 68kasm / src / a68kmisc.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  22KB  |  804 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*          Miscellaneous routines - March 20, 1988            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1988 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. char Sdata[MAXSREC];    /* S-record data */
  28. int  Sindex;        /* Index for Sdata */
  29. int  NumRExt, NumR32, NumR16, NumR8;
  30.  
  31. static char *errmsg[] =    {
  32.     "--- Unknown error code ---",
  33.     "Alignment error.",
  34.     "No such op-code.",
  35.     "Duplicate Symbol.",
  36.     "Undefined Symbol.",
  37.     "Addressing mode not allowed here.",
  38.     "Error in operand format.",
  39.     "Error in relative branch.",
  40.     "Address mode error.",
  41.     "Operand size error.",
  42.     "END statement is missing.",
  43.     "Value must be absolute.",
  44.     "Relocatability error.",
  45.     "Too many nested INCLUDEs.",
  46.     "INCLUDE file cannot be opened.",
  47.     "Illegal forward reference.",
  48.     "Not supported in S-format.",
  49.     "This instruction needs a label.",
  50.     "Pass 1 / Pass 2 phase error.",
  51.     "ENDM statement is missing.",
  52.     "Too much DC data.",
  53.     "Too many SECTIONs.",
  54.     "Duplicate macro definition.",
  55.     "More than one label on this line.",
  56.     "End of string is missing.",
  57.     "Short displacement can't be zero.",
  58.     ""};
  59.  
  60. /* Functions */
  61. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  62. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  63. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  64. extern long GetValue(),    CalcValue();
  65. extern char *malloc();
  66. extern FILE *fopen();
  67.  
  68. long AddrBndW(), AddrBndL();
  69.  
  70.  
  71.  
  72. long AddrBndW (v) long v;
  73. /* Advances "v" to the next word boundary */
  74. {
  75.     if (v & 1L)    {
  76.     AppendSdata (Srec, 0L, 1);
  77.     v++;
  78.     }
  79.     return (v);
  80. }
  81.  
  82.  
  83.  
  84. long AddrBndL (v) long v;
  85. /* Advances "v" to the next long-word boundary */
  86. {
  87.     long templong;
  88.  
  89.     v =    AddrBndW (v);        /* Bump    to word    boundary first */
  90.     if (v & 2L)    {        /* If still not    aligned, */
  91.     templong = NOP;        /*  generate a NOP */
  92.     AppendSdata (Srec, templong, 2);
  93.     v += 2;
  94.     }
  95.     return (v);
  96. }
  97.  
  98.  
  99.  
  100. WriteListLine (f) FILE *f;
  101. /* Writes one line to the Listing file,    including Object Code */
  102. {
  103.     register int i, j, printed;
  104.     long templong;
  105.     char macflag;
  106.  
  107.     if (errlim == 0)
  108.     if ((Dir == Page) || (Dir == Space) || (Dir == Title)
  109.     || (Dir    == DoList) || (Dir == NoList) || (ListOff))
  110.         return;        /* Don't print unless they have errors */
  111.  
  112.     CheckPage (f, FALSE);    /* Print headings if necessary */
  113.  
  114.     if (PrntAddr) {
  115.     if ((Dir == Equ) || (Dir == Set))
  116.         LongPut (f,    ObjSrc,    3);    /* Equated value */
  117.     else
  118.         LongPut (f,    AddrCnt, 3);    /* Current location */
  119.     if (!KeepTabs)
  120.         fprintf (f,    "  ");
  121.     } else
  122.     if (!KeepTabs)
  123.         fprintf (f,    "        ");    /* Don't print location */
  124.     if (KeepTabs)
  125.     fprintf    (f, "\t");              /* Use tabs for spacing */
  126.     printed = 8;            /* We've printed 8 positions */
  127.     LongPut (f,    ObjOp, nO);        /* Generated code */
  128.     printed += nO * 2;
  129.     if (nS != 0) {
  130.     fprintf    (f, " ");
  131.     LongPut    (f, ObjSrc, nS);
  132.     printed    += nS *    2 + 1;
  133.     }
  134.     if (nD != 0) {
  135.     fprintf    (f, " ");
  136.     LongPut    (f, ObjDest, nD);
  137.     printed    += nD *    2 + 1;
  138.     }
  139.     if ((j = nX) > 0) {                /* String data */
  140.     if ((j * 2 + printed) >    ObjMAX)
  141.         j =    (ObjMAX    - printed) / 2;
  142.     for (i = 0; i <    j; i++)    {
  143.         templong = ObjString[i];
  144.         LongPut (f,    templong, 1);
  145.     }
  146.     printed    += j * 2;
  147.     }
  148.     while (printed < ObjMAX) {
  149.     if (KeepTabs) {
  150.         fprintf (f,    "\t");
  151.         printed += 8;
  152.         printed &= ~7;
  153.     } else {
  154.         fprintf (f,    " ");
  155.         printed++;
  156.     }
  157.     }
  158.     if ((InFNum    == 0) || (OuterMac == 0))
  159.     macflag    = ' ';                  /* Open code */
  160.     else if (InFNum > OuterMac)
  161.     macflag    = '+';                  /* Inner macro */
  162.     else if ((InFNum ==    OuterMac) && (Dir != MacCall))
  163.     macflag    = '+';                  /* Outermost macro */
  164.     else
  165.     macflag    = ' ';                  /* We're outside macros */
  166.  
  167.     fprintf (f,    "  %5d%c%s\n", LineCount, macflag, Line);
  168.  
  169.     for    (i = 0;    i < errlim; i++) {    /* Write error messages. */
  170.     CheckPage (f, FALSE);
  171.     fprintf    (f, "%s", errmsg[errcode[i]]);
  172.     printed    = strlen(errmsg[errcode[i]]);
  173.     while (printed < ObjMAX    + 8) {
  174.         if (KeepTabs) {
  175.         fprintf    (f, "\t");
  176.         printed    += 8;
  177.         printed    &= ~7;
  178.         } else {
  179.         fprintf    (f, " ");
  180.         printed++;
  181.         }
  182.     }
  183.     for (j = 0; j <    errpos[i]; j++)    {
  184.         if (Line[j]    == '\t') {
  185.         fprintf    (f, "\t");
  186.         printed    += 8;
  187.         printed    &= ~7;
  188.         } else {
  189.         fprintf    (f, " ");
  190.         printed++;
  191.         }
  192.     }
  193.     fprintf    (f, "^ ");              /* Error flag */
  194.     if (i == 0) {
  195.         if (InF->UPtr == 0)
  196.         fprintf    (f, "%s", InF->NPtr);       /* Module name */
  197.         else
  198.         fprintf    (f, "(user macro)");        /* In a user macro */
  199.         fprintf (f,    " line %d", InF->Line);     /* Line number */
  200.     }
  201.     fprintf    (f, "\n");
  202.     }
  203. }
  204.  
  205.  
  206.  
  207. WriteSymTab (f)    FILE *f;
  208. /* Lists symbol    table in alphabetical order */
  209. {
  210.     int     printhunk, i;
  211.     char *p;
  212.     register int j, k;
  213.     struct SymTab *sym;
  214.     struct Ref      *ref;
  215.  
  216.     LnCnt = 999;            /* Skip    to a new page. */
  217.     for    (i = 0,    sym = SymStart;    i < NumSyms; i++, sym++) {
  218.     CheckPage (f, TRUE);
  219.  
  220.     p = sym->Nam;            /* Pointer to symbol */
  221.     while (*p == ' ')               /* Skip leading blanks, if any */
  222.         p++;
  223.     if (sym->Flags & 0x10)
  224.         p++;            /* Skip    hunk type flag in symbol */
  225.     fprintf    (f, "%-11s ", p);       /* Symbol or macro name */
  226.     if (strlen (p) > 11)        /* Long    symbol - go to new line    */
  227.         if (KeepTabs)
  228.         fprintf    (f, "\n\t    ");
  229.         else
  230.         fprintf    (f, "\n            ");
  231.  
  232.     printhunk = FALSE;        /* Assume no hunk no. to print */
  233.     if (sym->Defn == NODEF)
  234.         fprintf (f,    "  *** UNDEFINED *** ");
  235.     else if    (sym->Flags & 4)
  236.         fprintf (f,    "  -- SET Symbol --  ");
  237.     else if    (sym->Flags & 8)
  238.         fprintf (f,    " +++ MACRO +++  %4d", sym->Defn);
  239.     else if    (sym->Flags & 0x10) {
  240.         j =    (sym->Hunk & 0x3FFF0000L) >> 16;
  241.         if (j == HunkCode)
  242.         fprintf    (f, "  CODE    ");
  243.         else if (j == HunkData)
  244.         fprintf    (f, "  DATA    ");
  245.         else
  246.         fprintf    (f, "  BSS     ");
  247.         printhunk =    TRUE;
  248.     } else if (sym->Flags &    0x20) {
  249.         fprintf (f,    "      %c", (sym->Val & 8) ? 'A' : 'D');
  250.         fprintf (f,    "%d  ", sym->Val & 7);
  251.         printhunk =    TRUE;
  252.     } else {
  253.         LongPut (f,    sym->Val, 4);        /* Value */
  254.         fprintf (f,    "  ");
  255.         printhunk =    TRUE;
  256.     }
  257.     if (printhunk) {
  258.         j =    sym->Hunk & 0x00007FFFL;    /* Hunk    number */
  259.         if (sym->Flags & 0x60)
  260.         fprintf    (f, " Reg");            /* Register or list */
  261.         else if (sym->Hunk & 0x00008000L)
  262.         fprintf    (f, " Ext");            /* External */
  263.         else if (j == ABSHUNK)
  264.         fprintf    (f, " Abs");            /* Absolute */
  265.         else
  266.         fprintf    (f, "%4d", j);          /* Hunk number */
  267.         fprintf (f,    "  %4d", sym->Defn);    /* Statement no. */
  268.     }
  269.     if (XrefList) {
  270.         fprintf (f,    "  ");
  271.         if (sym->Ref1 == 0)
  272.         fprintf    (f, " *** UNREFERENCED ***");
  273.         else {
  274.         ref = sym->Ref1;
  275.         j = k =    0;
  276.         while (1) {
  277.             if (ref->RefNum[j] == 0)
  278.             break;
  279.             if (k >= 9)    {
  280.             fprintf    (f, "\n");              /* New line */
  281.             if (KeepTabs)
  282.                 fprintf (f,    "\t\t\t\t  ");
  283.             else
  284.                 for    (k = 0;    k < 34;    k++)
  285.                 fprintf    (f, " ");
  286.             k = 0;
  287.             }
  288.             fprintf (f,    " %4d", ref->RefNum[j]);
  289.             j++;
  290.             k++;
  291.             if (j < MAXREF)
  292.             continue;        /* Get the next    slot */
  293.             if ((ref = ref->NextRef) ==    0)
  294.             break;            /* End of last entry */
  295.             j =    0;            /* Start the next entry    */
  296.         }
  297.         }
  298.     }
  299.     fprintf    (f, "\n");
  300.     }
  301. }
  302.  
  303.  
  304.  
  305. CheckPage (f, xhdr) FILE *f; int xhdr;
  306. /* Checks if end of page reached yet --    if so, advances    to next    page. */
  307. {
  308.     register int printed;
  309.  
  310.     LnCnt++;
  311.     if (LnCnt >= LnMax)    {
  312.     PgCnt++;
  313.     if (PgCnt > 1)
  314.         fprintf (f,    "\f");                  /* Skip to new page */
  315.     fprintf    (f, "%s", TTLstring);           /* Title */
  316.     printed    = strlen(TTLstring);
  317.     while (printed < 56)
  318.         if (KeepTabs) {
  319.         fprintf    (f, "\t");
  320.         printed    += 8;
  321.         printed    &= ~7;
  322.         } else {
  323.         fprintf    (f, " ");
  324.         printed++;
  325.         }
  326.     fprintf    (f, "%s", SourceFN);            /* File name */
  327.     if (KeepTabs)
  328.         fprintf (f,    "\t");
  329.     else
  330.         fprintf (f,    "        ");
  331.     fprintf    (f, "Page %d\n\n\n", PgCnt);    /* Page number */
  332.     LnCnt =    3;
  333.     if (xhdr) {
  334.         fprintf (f,    "Symbol       Value    Hunk  Line");
  335.         if (XrefList)
  336.         fprintf    (f, "   References");   /* Cross-reference */
  337.         fprintf (f,    "\n\n");
  338.         LnCnt += 2;
  339.     }
  340.     }
  341. }
  342.  
  343.  
  344.  
  345. StartSrec (f, idntname)    FILE *f; char idntname[];
  346. /* Writes object header    record */
  347. {
  348.     register int i;
  349.     long CheckSum, templong;
  350.  
  351.     if (SFormat) {
  352.     fprintf    (f, "S0");
  353.     templong = strlen (idntname) + 3; /* extra for addr. & checksum    */
  354.     LongPut    (f, templong, 1);
  355.     CheckSum = templong;
  356.  
  357.     fprintf    (f, "0000");  /* Address is 4 digits, all zero, for S0 */
  358.  
  359.     for (i = 0; idntname[i]    != '\0'; i++) {
  360.         templong = toupper (idntname[i]);
  361.         LongPut (f,    templong, 1);
  362.         CheckSum +=    templong;
  363.     }
  364.     CheckSum = ~CheckSum;        /* Complement checksum */
  365.     LongPut    (f, CheckSum, 1);
  366.     fprintf    (f, "\n");
  367.     } else {
  368.     templong = HunkUnit;
  369.     putl (f, templong);
  370.     DumpName (f, idntname, 0L);
  371.     }
  372.     StartAddr =    TempAddr = Sindex = 0;
  373.     NumRExt = NumR32 = NumR16 =    NumR8 =    0;
  374. }
  375.  
  376.  
  377.  
  378. WriteSrecLine (f) FILE *f;
  379. /* Transfers object code components to output buffer. */
  380. /* Moves long words or portions    thereof. */
  381. {
  382.     register int i;
  383.     long templong;
  384.  
  385.     if (HunkType == HunkBSS)
  386.     return;                /* No code in BSS hunk */
  387.  
  388.     if (nO + nS    + nD + nX) {        /* If we have object code */
  389.     if (AddrCnt < TempAddr)    {    /*  and    location counter jumped    */
  390.         if (SFormat)        /*  and    we're making S-format, */
  391.         DumpSdata (f);        /*  get    rid of what we have */
  392.         StartAddr =    TempAddr = AddrCnt;    /*  and    start afresh. */
  393.     }
  394.     while (AddrCnt >= (TempAddr + 4))    /* It jumped forward - */
  395.         AppendSdata    (f, 0L,    4);        /*  fill with zeros    */
  396.     if (AddrCnt > TempAddr)    {
  397.         i =    AddrCnt    - TempAddr;
  398.         AppendSdata    (f, 0L,    i);
  399.     }
  400.     AppendSdata (f,    ObjOp, nO);        /* Op code */
  401.     AppendSdata (f,    ObjSrc,    nS);        /* Source */
  402.     AppendSdata (f,    ObjDest, nD);        /* Destination */
  403.     for (i = 0; i <    nX; i++) {        /* String data */
  404.         templong = ObjString[i];
  405.         AppendSdata    (f, templong, 1);
  406.     }
  407.     }
  408. }
  409.  
  410.  
  411.  
  412. AppendSdata (f,    Data, n) FILE *f; long Data; int n;
  413. /* If we are producing S-format    records:
  414.      Transfers "n" low-order bytes from "Data" to the output buffer.
  415.      If    the buffer becomes full, DumpSdata will    be called to flush it.
  416.      S-records will also be broken on 16-byte boundaries.
  417.    If we are producing AmigaDOS    format,    data will be written
  418.      directly to Srec -    we'll go back and fill in the hunk length
  419.      at    the end    of the hunk.  DumpSdata    will never be called from here.    */
  420. {
  421.     register int  i;
  422.     register char byte;
  423.     long templong;
  424.  
  425.     if (!Pass2)
  426.     return;            /* Pass    2 only */
  427.     if (HunkType == HunkBSS)
  428.     return;            /* No data in BSS hunks! */
  429.  
  430.     if (HunkType == HunkNone) {        /* We're not in a hunk yet - */
  431.     DoSection ("", 0, "", 0, "", 0);        /* start a code hunk */
  432.     MakeHunk = TRUE;
  433.     }
  434.     Data <<= (4    - n) * 8;    /* Left-justify    data */
  435.  
  436.     for    (i = 0;    i < n; i++) {
  437.     byte = (Data >>    ((3 - i) * 8)) & 0x00FF;
  438.     TempAddr++;
  439.     if (!SFormat)
  440.         putc (byte,    f);
  441.     else {
  442.         Sdata[Sindex++] = byte;
  443.         if (((TempAddr & 0x0F) == 0) || (Sindex >= MAXSREC))
  444.         DumpSdata (f);        /* Break S-record */
  445.     }
  446.     }
  447. }
  448.  
  449.  
  450.  
  451. DumpSdata (f) FILE *f;
  452. /* Writes an object code record    */
  453. {
  454.     register int  i;
  455.     register long CheckSum, templong;
  456.  
  457.     if (!SFormat) {
  458.     AddrCnt    = AddrBndL (AddrCnt);    /* Finish last long word */
  459.     templong = ftell (f);
  460.     fseek (f, LenPos, 0);    /* Hunk    length field is    here */
  461.     putl (f, ((AddrCnt - SectStart)    >> 2) |    HunkFlags);
  462.     fseek (f, templong, 0);    /* Back    to end of file */
  463.     DumpRel    (f);        /* Write relocation information    */
  464.     templong = HunkEnd;
  465.     putl (f, templong);    /* End of the hunk */
  466.     TempAddr = AddrCnt;
  467.     return;
  468.     }
  469.  
  470.     if (Sindex == 0)
  471.      return;        /* There's nothing to dump */
  472.  
  473.     fprintf (f,    "S2");
  474.     templong = Sindex +    4;    /* Record length */
  475.     LongPut (f,    templong, 1);
  476.     CheckSum = templong;    /* Initialize CheckSum */
  477.  
  478.     LongPut (f,    StartAddr, 3);    /* Address */
  479.     CheckSum +=    (StartAddr >> 16) & 0x00FF;
  480.     CheckSum +=    (StartAddr >> 8) & 0x00FF;
  481.     CheckSum +=    StartAddr & 0x00FF;
  482.  
  483.     for    (i = 0;    i < Sindex; i++) {
  484.     templong = Sdata[i];
  485.     LongPut    (f, templong, 1);    /* Object code */
  486.     CheckSum += templong;
  487.     }
  488.     CheckSum = ~CheckSum;    /* Complement checksum */
  489.     LongPut (f,    CheckSum, 1);
  490.     fprintf (f,    "\n");
  491.  
  492.     StartAddr += Sindex;
  493.     TempAddr = StartAddr;
  494.     Sindex = 0;
  495. }
  496.  
  497.  
  498.  
  499. PutRel (addr, hunk, size) long addr, hunk; int size;
  500. /* Build a relocation entry if necessary */
  501. {
  502.     struct RelTab *rel;
  503.  
  504.     if (!Pass2)    return;            /* Pass    2 only */
  505.     if (SFormat) return;        /* Not for S-format! */
  506.     if (hunk ==    ABSHUNK) return;    /* Absolute */
  507.     if (HunkType == HunkBSS) return;    /* Not for BSS hunks! */
  508.  
  509.     HeapSpace (sizeof(struct RelTab));    /* Make    sure we    have room */
  510.     rel    = (struct RelTab *) HeapLim;    /* Pointer to new entry    */
  511.     rel->Offset    = addr;            /* Offset */
  512.     rel->Hunk =    hunk;            /* Hunk    number */
  513.     rel->Size =    size;            /* Size    */
  514.     HeapLim += sizeof(struct RelTab);    /* Bump    heap limit pointer */
  515.  
  516.     if (hunk < 0)            /* Count entries by type */
  517.     NumRExt++;
  518.     else if (size == Long)
  519.     NumR32++;
  520.     else if (size == Word)
  521.     NumR16++;
  522.     else
  523.     NumR8++;
  524. }
  525.  
  526.  
  527.  
  528. DumpRel    (f) FILE *f;
  529. /* Dump    relocation information to the object file. */
  530. {
  531.     register struct SymTab *sym;
  532.     register struct RelTab *rel, *rel2;
  533.     int     i, j, size, num, donexhdr, secthlin;
  534.     long currhunk, nexthunk, templong;
  535.     char *p;
  536.  
  537.     if (SFormat)
  538.     return;                /* S-format is absolute! */
  539.  
  540.     secthlin = LineCount;        /* Current section ends    here */
  541.     if (strcmp (OpCode,"SECTION") == 0) /*   unless we're starting   */
  542.     secthlin--;            /*    a new section.         */
  543.  
  544.     while (1) {
  545.     if ((num = NumR32) != 0) {
  546.         size = Long;        /* Do 32-bit fields */
  547.         templong = HunkR32;
  548.         NumR32 = 0;            /* ...but only once */
  549.     } else if ((num    = NumR16) != 0)    {
  550.         size = Word;        /* Then    do 16-bit fields */
  551.         templong = HunkR16;
  552.         NumR16 = 0;
  553.     } else if ((num    = NumR8) != 0) {
  554.         size = Byte;        /* Finally do 8-bit fields */
  555.         templong = HunkR8;
  556.         NumR8 = 0;
  557.     } else
  558.         break;            /* We're all done */
  559.  
  560.     putl (f, templong);        /* Record type */
  561.  
  562.     currhunk = 32767;
  563.     num = 0;
  564.     for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  565.         if ((rel->Size == size) && (rel->Hunk >= 0)) {
  566.         if (rel->Hunk <    currhunk) {
  567.             currhunk = rel->Hunk;    /* Lowest hunk number */
  568.             num    = 1;            /* Reset counter */
  569.         } else if (rel->Hunk ==    currhunk) {
  570.             num++;            /* Count entries */
  571.         }
  572.         }
  573.     }
  574.     while (num > 0)    {    /* Repeat for all hunk references */
  575.         templong = num;
  576.         putl (f, templong);        /* Number of entries */
  577.         putl (f, currhunk);        /* Hunk    number */
  578.         nexthunk = 32767;
  579.         num    = 0;            /* Count for next hunk */
  580.         for    (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  581.         if ((rel->Size == size)    && (rel->Hunk >= 0)) {
  582.             if (rel->Hunk < currhunk)
  583.             continue;        /* Already wrote it */
  584.             else if (rel->Hunk == currhunk)
  585.             putl (f, rel->Offset - SectStart);
  586.             else if (rel->Hunk < nexthunk) {
  587.             nexthunk = rel->Hunk;    /* Next    hunk number */
  588.             num = 1;        /* Reset counter */
  589.             } else if (rel->Hunk == nexthunk) {
  590.             num++;            /* Count entries */
  591.             }
  592.         }
  593.         }
  594.         currhunk = nexthunk;    /* Get ready for next hunk */
  595.     }
  596.     putl (f, 0L);        /* End of relocation information */
  597.     }
  598.  
  599.     donexhdr = FALSE;        /* Haven't written hunk_ext yet */
  600.  
  601.     for    (i = 0,    sym = SymStart;    i < NumSyms; i++, sym++) {
  602.     if (sym->Flags & 2) {        /* Scan    for XDEF symbols */
  603.         j =    sym->Defn;    /* Defined in current section? */
  604.         if ((j >= SectLine)    && (j <= secthlin)) {
  605.         if (!donexhdr) {
  606.             templong = HunkExt;    /* Haven't done header yet */
  607.             putl (f, templong);
  608.             donexhdr = TRUE;
  609.         }
  610.         if ((sym->Hunk & 0x0000FFFFL) == ABSHUNK)
  611.             templong = 0x02000000;
  612.         else
  613.             templong = 0x01000000;        /* Flags */
  614.         DumpName (f, sym->Nam, templong);    /* Symbol */
  615.         putl (f, sym->Val - SectStart);        /* Offset */
  616.         }
  617.     }
  618.     }
  619.  
  620.     if (NumRExt    != 0) {            /* External references (XREF) */
  621.     if (!donexhdr) {
  622.         templong = HunkExt;        /* Haven't done header yet */
  623.         putl (f, templong);
  624.         donexhdr = TRUE;
  625.     }
  626.     for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  627.         if (rel->Hunk < 0) {
  628.         p = Heap + ~rel->Hunk;
  629.         size = rel->Size;
  630.         if (size == Long)
  631.             templong = 0x81000000;    /* ext_ref32 */
  632.         else if    (size == Word)
  633.             templong = 0x83000000;    /* ext_ref16 */
  634.         else
  635.             templong = 0x84000000;    /* ext_ref8 */
  636.         DumpName (f, p,    templong);    /* Flags and symbol */
  637.         templong = 1;
  638.         for (rel2 = rel    + 1; rel2 < (struct RelTab *) HeapLim; rel2++)
  639.             if ((rel2->Hunk == rel->Hunk) && (rel2->Size == size))
  640.             templong++;        /* Number of times */
  641.         putl (f, templong);        /*  symbol occurs  */
  642.         for (rel2 = rel; rel2 <    (struct    RelTab *) HeapLim; rel2++) {
  643.             if ((rel2->Hunk == rel->Hunk) && (rel2->Size == size)) {
  644.             putl (f, rel2->Offset -    SectStart); /* Offset */
  645.             if (rel2 != rel)    /* Kill    hunk so    we    */
  646.                 rel2->Hunk = 0;    /*  don't do it again */
  647.             }                /*  (we're done with  */
  648.         }                /*  the    table anyway) */
  649.         }
  650.     }
  651.     NumRExt    = 0;
  652.     }
  653.     if (donexhdr)
  654.     putl (f, 0L);            /* End of external information */
  655.  
  656.     if (DumpSym) {            /* Dump    the symbol table */
  657.     donexhdr = FALSE;
  658.     for (i = 0, sym    = SymStart; i <    NumSyms; i++, sym++) {
  659.         if (((sym->Hunk & 0x0000FFFFL) == CurrHunk)
  660.         && ((sym->Flags == 0) || (sym->Flags == 2))) {
  661.         j = sym->Defn;        /* Defined in current section? */
  662.         if ((j >= SectLine) && (j <= secthlin))    {
  663.             if (!donexhdr) {
  664.             templong = HunkSym;        /* Header */
  665.             putl (f, templong);
  666.             donexhdr = TRUE;
  667.             }
  668.             DumpName (f, sym->Nam, 0L);        /* Symbol */
  669.             putl (f, sym->Val -    SectStart);    /* Offset */
  670.         }
  671.         }
  672.     }
  673.     if (donexhdr)
  674.         putl (f, 0L);        /* End of symbol table dump */
  675.     }
  676.  
  677.     if (HeapLim    > HighHeap)
  678.     HighHeap = HeapLim;        /* High-water mark */
  679.     HeapLim = (char *) RelStart;    /* Reset heap limit */
  680. }
  681.  
  682.  
  683.  
  684. EndSdata (f, addr) FILE    *f; long addr;
  685. /* Write end record to object file */
  686. {
  687.     register long checksum, templong;
  688.  
  689.     if (SFormat) {
  690.     DumpSdata (f);            /* Write any remaining data */
  691.     fprintf    (f, "S804");            /* Record header */
  692.     checksum = 4;
  693.     LongPut    (f, addr, 3);        /* Transfer address */
  694.     checksum += (addr >> 16) & 0x00FF;
  695.     checksum += (addr >> 8)    & 0x00FF;
  696.     checksum += addr & 0x00FF;
  697.     checksum = ~checksum;
  698.     LongPut    (f, checksum, 1);    /* Checksum */
  699.     fprintf    (f, "\n");
  700.     } else {
  701.     if (HunkType !=    HunkNone) {
  702.         DumpSdata (f);        /* Last    hunk's data */
  703.     }
  704.     }
  705. }
  706.  
  707.  
  708.  
  709. DumpName (f, name, flags) FILE *f; char    name[];    long flags;
  710. /* Writes a name preceded by a long word containing the
  711.     length of the name in long words.  The length word has
  712.     the    contents of "flags" ORed into it.  The name is padded
  713.     with binary    zeros to the next long word boundary. */
  714. {
  715.     register int  i;
  716.     register long templong;
  717.  
  718.     templong = (strlen (name) +    3) >> 2;    /* Length (long    words) */
  719.     templong |=    flags;                /* Add flag bits */
  720.     putl (f, templong);
  721.     i =    0;
  722.     while (name[i])
  723.     putc (name[i++], f);            /* Write a byte    */
  724.     while (i & 3) {
  725.     putc ('\0', f);                         /* Pad the last word */
  726.     i++;
  727.     }
  728. }
  729.  
  730.  
  731.  
  732. LongPut    (f, data, length) FILE *f; long    data; int length;
  733. /* Writes to file "f" the hexadecimal interpretation of
  734.     the    bytes in "data".  The number of bytes written
  735.     (two hex digits per    byte) is given in "length" -
  736.     if less than 4, only low-order bytes are written. */
  737. {
  738.     register int i, j, k;
  739.  
  740.     for    (i = length - 1; i >= 0; i--) {
  741.     j = (data >> (i    * 8)) &    0x00FF;
  742.     k = j >> 4;
  743.     fprintf    (f, "%c", k>9 ? k-10+'A' : k+'0');
  744.     k = j &    0x0F;
  745.     fprintf    (f, "%c", k>9 ? k-10+'A' : k+'0');
  746.     }
  747. }
  748.  
  749.  
  750.  
  751. putl (f, data) FILE *f;    long data;
  752. /* Writes to file "f" the binary contents of "data" */
  753. {
  754.     register int  i;
  755.     register char byte;
  756.  
  757.     for    (i = 0;    i < 4; i++) {
  758.     byte = (data >>    ((3 - i) * 8)) & 0x00FF;
  759.     putc (byte, f);
  760.     }
  761. }
  762.  
  763.  
  764.  
  765. Error (pos, errornum) int pos, errornum;
  766. /* Displays error message #errornum.  If this is the first error for
  767.     the    current    line, the line itself is displayed, preceded by    a
  768.     message giving the current position    in the current module.
  769.     If the line    is in a    macro or include file, the position in
  770.     each nested    module is given, working out to    the source file.
  771.     A flag is placed under the column indicated    by "pos".       */
  772. {
  773.     register struct InFCtl *inf;
  774.     register int i;
  775.  
  776.     if (!Pass2)
  777.     return;                /* Active during pass 2    only */
  778.  
  779.     if (errlim < ERRMAX) {        /* Save    error data */
  780.     errcode[errlim]    = errornum;
  781.     errpos[errlim] = pos;
  782.     errlim++;
  783.     }
  784.     if (errlim == 1) {        /* First error for this    line? */
  785.     printf ("    \n");                      /* Wipe out line counter */
  786.     for (i = InFNum, inf = InF; i >= 0; i--, inf++)    {   /* Nested? */
  787.         if (inf->UPtr == 0)
  788.         printf ("%s", inf->NPtr);       /* Module name */
  789.         else
  790.         printf ("(user macro)");        /* In a user macro */
  791.         printf (" line %d\n", inf->Line);   /* Line number in module */
  792.     }
  793.     printf ("%5d   %s\n", LineCount, Line); /* Line in error */
  794.     }
  795.     printf ("\t");
  796.     for    (i = 0;    i < pos; i++)
  797.     if (Line[i] == '\t')
  798.         printf ("\t");
  799.     else
  800.         printf(" ");                /* Space over to error column */
  801.     printf ("^ %s\n",errmsg[errornum]); /* Error flag and message */
  802.     ErrorCount++;            /* Count errors    */
  803. }
  804.